﻿#ifndef SYNCVECTOR_H
#define SYNCVECTOR_H

#include <vector>
#include "mutex.h"
#include "semaphore.h"
#include "guard.h"
#include "remote_obj_error.h"

namespace RemoteObj
{
using namespace std;

template<typename ElemType>
class SyncVector
{
public:
    SyncVector() {};
    ~SyncVector() {};
    typedef Guard<Mutex> ScopedGuard;
    int32_t get(ElemType & elem, int32_t millisecond)
    {
        int32_t ret = _sem.wait(millisecond);

        if (0 == ret)
        {
            {
                ScopedGuard guard(&_mutex);
                if (guard.is_locked())
                {
                    elem = _vector.back();
                    _vector.pop_back();
                }
                else
                {
                    return E_REMOTEOBJ_SYSERROR;
                }
            }
            return 0;
        }
        else
        {
            return ret;
        }
    }

    int32_t put(ElemType elem)
    {
        ScopedGuard guard(&_mutex);
        if (guard.is_locked())
        {
            try
            {
                _vector.push_back(elem);
            }
            catch(std::bad_alloc &)
            {
                return E_REMOTEOBJ_NOMEM;
            }
        }
        else
        {
            return E_REMOTEOBJ_SYSERROR;
        }
        _sem.signal();
        return 0;
    }

protected:
    SyncVector(const SyncVector&);
    SyncVector& operator=(const SyncVector&);
private:
    vector<ElemType> _vector;
    Mutex _mutex;
    Semaphore _sem;

};
}
#endif // SYNCVECTOR_H
